//#include "stdafx.h"
#include "byteBuffer.h"

ByteBuffer::ByteBuffer(const uint8* buf, size_t size)
:_rpos(0), _wpos(0)
{
	ASSERT(0 <= size);
	
	_storage.reserve(255);
	_storage.resize(size);
	memcpy(&_storage[0], buf, size);
}

ByteBuffer& ByteBuffer::operator= (const ByteBuffer& r)
{
	if (this != &r)
	{
		_rpos = r._rpos;
	   	_wpos = r._wpos;
		_storage = r._storage;
	}

	return *this;
}

void ByteBuffer::_Write(const uint8 *src, size_t size)
{
	if(size < 0)
		throw ByteBufferException("ByteBuffer::_Write, size < 0");


	if (_storage.size() < _wpos + size)
		_storage.resize(_wpos + size);

	memcpy(&_storage[_wpos], src, size);
	_wpos += size;
}

void ByteBuffer::_Read(uint8 *dest, size_t size)
{
	if (size < 0)
		throw ByteBufferException("ByteBuffer::_Read, size < 0");

	if (_rpos + size > _storage.size())
		throw ByteBufferException("ByteBuffer::_Read, data doesn't match");
	
	memcpy(dest, &_storage[_rpos],  size);
	_rpos += size;
}

ByteBuffer& ByteBuffer::operator<<(const string &value)
{
	uint16 size = value.size();
	uint16 size_big_endian = htons(size); 
	_Write<uint16>(size_big_endian);
	if(size != 0)
		_Write((const uint8*)value.c_str(), size);

	return *this;
}

ByteBuffer& ByteBuffer::operator>>(string &value)
{
	uint16 size_big_endian = 0;
	_Read<uint16>(size_big_endian);
	uint16 size = ntohs(size_big_endian);

	if(size != 0)
	{
		uint8* tmp = SAFE_NEW uint8[size];
		memset(tmp, 0, size);
		_Read(tmp, size);
		value.append((char*)tmp);
		SAFE_DELETE_ARRAY(tmp);
	}

	return *this;
}

ByteBuffer& ByteBuffer::operator<<(ByteBuffer &value)
{
	uint16 size = value.Left();
	uint16 size_big_endian = htons(size);
	_Write<uint16>(size_big_endian);

	if(size != 0)
	{
		uint8* tmp = SAFE_NEW uint8[size];
		memset(tmp, 0, size);
		value._Read(tmp, size);
		_Write(tmp, size);
		SAFE_DELETE_ARRAY(tmp);
	}

	return *this;
}

ByteBuffer& ByteBuffer::operator>>(ByteBuffer &value)
{	
	uint16 size_big_endian = 0;
	_Read<uint16>(size_big_endian);
	uint16 size = ntohs(size_big_endian);

	if(size != 0)
	{
		uint8* tmp = SAFE_NEW uint8[size];
		memset(tmp, 0, size);
		_Read(tmp, size);
		value._Write(tmp, size);
		SAFE_DELETE_ARRAY(tmp);
	}

	return *this;
}

ByteBuffer& ByteBuffer::operator<<(float value) 
{
	uint32 tmp = 0;
	memcpy(&tmp, &value, sizeof(float));
	_Write<uint32>(htonl(tmp)); 

	return *this;
}

ByteBuffer& ByteBuffer::operator>>(float &value) 
{
	uint32 tmp = 0;
	_Read<uint32>(tmp); 
	tmp = ntohl(tmp);
	memcpy(&value, &tmp, sizeof(float));

	return *this; 
}

ByteBuffer& ByteBuffer::operator<<(double value) 
{
	int64 tmp = 0;
	memcpy(&tmp, &value, sizeof(double));
	_Write<int64>(BITSWAP64(tmp));

	return *this; 
}

ByteBuffer& ByteBuffer::operator>>(double &value) 
{
	int64 tmp = 0;
	_Read<int64>(tmp);
	tmp = BITSWAP64(tmp);
	memcpy(&value, &tmp, sizeof(double));

	return *this;
}